package com.service.infoEntry.service.impl;

import com.service.config.utils.DateUtil;
import com.service.config.utils.DateUtils;
import com.service.config.utils.IdUtil;
import com.service.config.utils.ModelMapperUtil;
import com.service.infoEntry.dao.CityDao;
import com.service.infoEntry.dao.RouteInfoDao;
import com.service.infoEntry.dao.UserInfoDao;
import com.service.infoEntry.dto.RouteDto;
import com.service.infoEntry.dto.UserDto;
import com.service.infoEntry.entity.CityInfo;
import com.service.infoEntry.entity.RouteInfo;
import com.service.infoEntry.entity.UserInfo;
import com.service.infoEntry.service.RouteInfoService;
import com.service.infoEntry.vo.RouteVo;
import com.service.infoEntry.vo.UserVo;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * 行程信息表(RouteInfo)表服务实现类
 *
 * @author makejava
 * @since 2021-09-24 16:50:52
 */
@Service("routeInfoService")
public class RouteInfoServiceImpl implements RouteInfoService {
    @Resource
    private RouteInfoDao routeInfoDao;
    @Resource
    private UserInfoDao userInfoDao;
    @Resource
    private CityDao cityDao;

    private final String dateFormat="yyyy-MM-dd";
    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public RouteInfo queryById(String id) {
        return this.routeInfoDao.queryById(id);
    }

    /**
     * 查询多条数据
     *
     * @param teamId 查询起始位置
     * @param username  模糊查询
     * @return 对象列表
     */
    @Override
    public List<RouteVo> queryAllRouteOfTeamUser(String teamId, String userId, String startDateStr, String username,Integer status) throws ParseException {
//        SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd");
        List<RouteVo> routeVos=new ArrayList<>();
        RouteVo routeVo;
        UserDto userDto;
        List<RouteInfo> routeInfos;
        List<RouteDto> routeDtos;


//        Date startDate = sf.parse(startDateStr);
        Date startDate = DateUtils.dateTime(dateFormat, startDateStr);

        Calendar c=Calendar.getInstance();
        c.setTime(startDate);
        c.add(Calendar.DAY_OF_MONTH,7);
        Date endDate=c.getTime();

//        String endDateStr = sf.format(endDate.getTime());
        String endDateStr = DateUtils.parseDateToStr(dateFormat, endDate);

        if(username!=null && !"".equals(username))
        {
            username="%"+username+"%";
        }
        List<UserInfo> userInfos = userInfoDao.queryAllUserInTeamWithName(teamId,username);
        //设置用户常驻地
        userInfos.forEach(userInfo -> {
            if(null==userInfo.getDefaultAddress() || "".equals(userInfo.getDefaultAddress()))
            {
                userInfo.setDefaultAddress("待定");
            }
        });

        //遍历团队下所有用户，查询每个用户的行程信息
        //从数据库查询时间段数据，匹配到用户
        List<RouteInfo> tempRouteInfoList = routeInfoDao.queryRoutes(startDateStr, endDateStr);
        for (UserInfo userInfo : userInfos) {
            routeVo=new RouteVo();
            userDto=ModelMapperUtil.strictMap(userInfo,UserDto.class);
            routeInfos = tempRouteInfoList.stream().filter(tempRouteInfo -> tempRouteInfo.getUserId().equals(userInfo.getId())).collect(Collectors.toList());
            routeDtos = this.parseUserRoute(routeInfos, userDto, startDateStr);
            routeVo.setUserVo(ModelMapperUtil.strictMap(userInfo, UserVo.class));
            routeVo.setRouteDtos(routeDtos);
            routeVos.add(routeVo);
        }

        //将当前userId用户的行程单放在首位
        RouteVo tempRoute;
        for(int i=0;i<routeVos.size();i++)
        {
            if(routeVos.get(i).getUserVo().getId().equals(userId))
            {
                tempRoute = routeVos.get(0);
                routeVos.set(0,routeVos.get(i));
                routeVos.set(i,tempRoute);
            }
        }

        //判断是否是查询有出差计划的人员
        if(null!=status && status==1)
        {
            return routeVos.stream().filter(this::checkIsOut).collect(Collectors.toList());
        }
        return routeVos;
    }

    /**
     * 判断行程中是否有出差安排
     * @param routeVo
     * @return
     */
    public boolean checkIsOut(RouteVo routeVo)
    {
        AtomicBoolean flag= new AtomicBoolean(false);
        routeVo.getRouteDtos().forEach(routeDto -> {
            if (routeDto.getStatus()==1)
            {
                flag.set(true);
                return;
            }
        });
        return flag.get();
    }

    /**
     * 新增数据
     *
     * @param routeInfo 实例对象
     * @return 实例对象
     */
    @Override
    public RouteInfo insert(RouteInfo routeInfo) {
        routeInfo.setId(IdUtil.getStringId());
        routeInfo.setUpdateTime(DateUtils.getNowDate());
        routeInfo.setAddTime(DateUtils.getNowDate());
        this.routeInfoDao.insert(routeInfo);
        return routeInfo;
    }

    /**
     * 修改数据
     *
     * @param routeDtos 实例对象
     * @return 实例对象
     */
    @Override
    public void update(List<RouteDto> routeDtos,UserDto userDto) {
//        SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd");
        routeDtos.forEach(routeDto ->
        {
            RouteInfo routeInfo;
            routeDto.setUserId(userDto.getId());
            routeDto.setUsername(userDto.getUsername());
            routeDto.setUpdateTime(DateUtils.getNowDate());
            //插入记录
            if(null==routeDto.getId() || "".equals(routeDto.getId()))
            {
                Date parse = null;
                routeDto.setId(IdUtil.getStringId());
                routeDto.setAddTime(DateUtils.getNowDate());
//                    parse = sf.parse(routeDto.getDateTimeStr());
                parse = DateUtils.dateTime(dateFormat,routeDto.getDateTimeStr());
                routeDto.setDateTime(parse);
                routeInfo = ModelMapperUtil.strictMap(routeDto, RouteInfo.class);
                routeInfoDao.insert(routeInfo);
            }else {
                //修改记录
                routeInfo = ModelMapperUtil.strictMap(routeDto, RouteInfo.class);
                if(routeInfo.getStatus()==3)
                {
                    routeInfo.setAddress("待定");
                }
                routeInfoDao.update(routeInfo);
            }
        });
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(String id) {
        return this.routeInfoDao.deleteById(id) > 0;
    }

    /**
     * 根据用户id查询该用户下所有的行程
     * @param userDto 用户对象
     * @param startDateStr 开始日期
     * @return
     */
    @Override
    public RouteVo queryRouteByUser(UserDto userDto, String startDateStr) throws ParseException {
        RouteVo routeVo=new RouteVo();
//        SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd");
        Calendar c=Calendar.getInstance();
//        Date startDate = sf.parse(startDateStr);
        Date startDate = DateUtils.dateTime(dateFormat, startDateStr);
        c.setTime(startDate);
        c.add(Calendar.DAY_OF_MONTH,7);
        Date endDate=c.getTime();
//        String endDateStr = sf.format(endDate.getTime());
        String endDateStr = DateUtils.parseDateToStr(dateFormat,endDate);

        //从数据库查询时间段数据，匹配到用户
        List<RouteInfo> tempRouteInfoList = routeInfoDao.queryRoutes(startDateStr, endDateStr);
        List<RouteInfo> routeInfoList = tempRouteInfoList.stream().filter(tempRouteInfo -> tempRouteInfo.getUserId().equals(userDto.getId())).collect(Collectors.toList());

        List<RouteDto> routeDtos = this.parseUserRoute(routeInfoList, userDto, startDateStr);

        routeVo.setUserVo(ModelMapperUtil.strictMap(userDto, UserVo.class));
        routeVo.setRouteDtos(routeDtos);
        return routeVo;
    }

    /**
     * 从查询到的某时间段的所有行程中筛选出该用户的行程，行程缺失则填充
     * @param routeInfoList
     * @param userDto
     * @param startDateStr
     * @return
     * @throws ParseException
     */
    public List<RouteDto> parseUserRoute(List<RouteInfo> routeInfoList,UserDto userDto,String startDateStr) throws ParseException {
        List<RouteDto> routeDtos = new ArrayList<>();
        RouteDto routeDto;
//        SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd");
        Calendar c=Calendar.getInstance();

//        Date startDate = sf.parse(startDateStr);
        Date startDate = DateUtils.dateTime(dateFormat, startDateStr);
        c.setTime(startDate);

        //判断用户下是否有行程，没有需要填充七个对象
        if(routeInfoList!=null && routeInfoList.size()==0)
        {
            for (int i=0;i<7;i++)
            {
                routeDto=new RouteDto();
                //从当天开始计算，一共七天，填充七个对象
                if(i>0)
                {
                    c.add(Calendar.DAY_OF_MONTH,1);
                }
//                routeDto.setDateTimeStr(sf.format(c.getTime()));
                routeDto.setDateTimeStr(DateUtils.parseDateToStr(dateFormat,c.getTime()));

                routeDto.setUserId(userDto.getId());
                routeDto.setUsername(userDto.getUsername());

//                routeDto.setDayOfWeek(parseDayOfWeek(c.get(Calendar.DAY_OF_WEEK)-1));
                routeDto.setDayOfWeek(DateUtil.dateToWeek(DateUtils.parseDateToStr(dateFormat,c.getTime())));
                //默认在常驻地
                routeDto.setStatus(3);
                routeDto.setStatusStr(parseStatus(routeDto.getStatus()));
                //出差地址未填写时，默认填充为"待定"
                this.parseRoute(routeDto);
                routeDtos.add(routeDto);
            }
        }else if(null!=routeInfoList && routeInfoList.size()>0)
        {
            boolean flag;
            //判断用户七天中是否行程满，不满则填充
            for(int i=0;i<7;i++)
            {
                flag=false;
                routeDto=new RouteDto();

//                String format = sf.format(c.getTime());
                String format=DateUtils.parseDateToStr(dateFormat,c.getTime());

                for (RouteInfo routeInfo : routeInfoList) {
                    //判断当前的c日期是否有行程
//                    if(sf.format(routeInfo.getDateTime()).equals(format))
                    if(DateUtils.parseDateToStr(dateFormat,routeInfo.getDateTime()).equals(format))
                    {
                        Date parse = routeInfo.getDateTime();
                        c.setTime(parse);
                        routeDto = ModelMapperUtil.strictMap(routeInfo, RouteDto.class);
                        //出差地址未填写时，默认填充为"待定"
                        this.parseRoute(routeDto);
//                        routeDto.setDateTimeStr(sf.format(routeInfo.getDateTime()));
                        routeDto.setDateTimeStr(DateUtils.parseDateToStr(dateFormat,routeInfo.getDateTime()));

                        routeDto.setStatusStr(parseStatus(routeInfo.getStatus()));
//                        routeDto.setDayOfWeek(parseDayOfWeek(c.get(Calendar.DAY_OF_WEEK)-1));
                        routeDto.setDayOfWeek(DateUtil.dateToWeek(DateUtils.parseDateToStr(dateFormat,c.getTime())));
                        routeDtos.add(routeDto);
                        flag=true;
                    }
                }
                //填充空白行程
                if(false==flag)
                {
                    routeDto.setUserId(userDto.getId());
                    routeDto.setUsername(userDto.getUsername());
//                    routeDto.setDateTimeStr(sf.format(c.getTime()));
                    routeDto.setDateTimeStr(DateUtils.parseDateToStr(dateFormat,c.getTime()));

                    routeDto.setDayOfWeek(DateUtil.dateToWeek(DateUtils.parseDateToStr(dateFormat,c.getTime())));

                    //默认在常驻地
                    routeDto.setStatus(3);
                    routeDto.setStatusStr(parseStatus(routeDto.getStatus()));

                    //出差地址未填写时，默认填充为"待定"
                    this.parseRoute(routeDto);
                    routeDtos.add(routeDto);
                }
                //以当前日期为标准，向前移一天
                c.add(Calendar.DAY_OF_MONTH,1);
            }
        }
        return routeDtos;
    }

    public RouteDto parseRoute(RouteDto routeDto)
    {
        if(routeDto.getAddress()==null || "".equals(routeDto.getAddress()))
        {
            routeDto.setAddress("待定");
        }
        return routeDto;
    }

    @Override
    public List<RouteInfo> queryAllByDate(String startDate, String endDate) {
        List<RouteInfo> routeInfoList = routeInfoDao.queryAllByDate(startDate,endDate);
        return routeInfoList;
    }

    @Override
    public void insertBatch(List<RouteInfo> routeInfoList) {
        routeInfoDao.insertBatch(routeInfoList);
    }

    @Override
    public void addCity(UserDto userDto, String cityName) {
        CityInfo cityEntity=new CityInfo();
        cityEntity.setId(IdUtil.getStringId());
        cityEntity.setCity(cityName);
        cityEntity.setUserId(userDto.getId());
        cityEntity.setUsername(userDto.getUsername());
        cityEntity.setAddTime(DateUtils.getNowDate());
        cityDao.addCity(cityEntity);
    }

    @Override
    public Map<String,List<String>> queryCity(String userId) {
        List<String> cities=new ArrayList<>();
        Map<String,List<String>> map=new HashMap<>();
        List<CityInfo> cityInfos = cityDao.queryCities(userId);
        if(null!=cityInfos && cityInfos.size()>0)
        {
            Collections.sort(cityInfos, new Comparator<CityInfo>() {
                @Override
                public int compare(CityInfo o1, CityInfo o2) {
                    return (int) (o2.getAddTime().getTime()-o1.getAddTime().getTime());
                }
            });
            for (int i=0;i<5;i++)
            {
                cities.add(cityInfos.get(i).getCity());
            }
        }
        map.put("cities",cities);
        return map;
    }

    @Override
    public void updateCity(String userId, String cityName) {
        CityInfo cityInfo=new CityInfo();
        cityInfo.setAddTime(DateUtils.getNowDate());
        cityInfo.setUserId(userId);
        cityInfo.setCity(cityName);
        cityDao.updateCity(cityInfo);
    }

    /**
     * 3是待定
     * @param status
     * @return
     */
    public String parseStatus(Integer status)
    {
        switch (status)
        {
            case 0:
                return "常驻地";
            case 1:
                return "出差";
            case 2:
                return "出差在途";
            case 3:
                return "待定";
            default:
                return "";
        }
    }

    public String parseDayOfWeek(Integer dayOfWeek)
    {
        switch (dayOfWeek)
        {
            case 0:
                return "周日";
            case 1:
                return "周一";
            case 2:
                return "周二";
            case 3:
                return "周三";
            case 4:
                return "周四";
            case 5:
                return "周五";
            case 6:
                return "周六";
            default:
                return "";
        }
    }
}
